package com.roher.gmws.myapplication;

import android.Manifest;
import android.content.pm.PackageManager;
import android.media.AudioFormat;
import android.media.AudioManager;
import android.media.AudioRecord;
import android.media.AudioTrack;
import android.media.MediaPlayer;
import android.media.MediaRecorder;
import android.os.Bundle;
import android.os.Environment;

import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;

import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.Toast;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.concurrent.LinkedBlockingQueue;

public class MainActivity extends AppCompatActivity {

    private static class Buffer {
        Buffer(int bufferSize) {
            this.bufferSize = bufferSize;
            buffer = new byte[bufferSize];
            offset = 0;
        }

        byte[] buffer;
        int offset;
        int bufferSize;
    }

    private static final int REQUEST_RECORD_AUDIO_PERMISSION = 200;
    private MediaRecorder mediaRecorder;
    private MediaPlayer mediaPlayer;
    private String fileName;
    private boolean isRecording = false;
    private AudioRecord mAudioRecord;
    Thread mReadAudioThread;
    Thread mSaveAudioThread;
    private LinkedBlockingQueue<Buffer> mBufferQueue = new LinkedBlockingQueue<>();
    private Button recordButton;
    private Button playButton;

    // 权限请求
    private String[] permissions = {Manifest.permission.RECORD_AUDIO};

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        recordButton = findViewById(R.id.recordButton);
        playButton = findViewById(R.id.playButton);

        // 设置文件路径为应用的私有目录
        fileName = getExternalFilesDir(null).getAbsolutePath() + "/recorded_audio.3gp";

        // 请求录音权限
        if (ContextCompat.checkSelfPermission(this, Manifest.permission.RECORD_AUDIO) != PackageManager.PERMISSION_GRANTED) {
            ActivityCompat.requestPermissions(this, permissions, REQUEST_RECORD_AUDIO_PERMISSION);
        }

        // 录音按钮点击事件
        recordButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                if (isRecording) {
                    stopRecording();
                    recordButton.setText("开始录音");
                    isRecording = false;
                } else {
                    startRecording();
                    recordButton.setText("停止录音");
                    isRecording = true;
                }
            }
        });

        // 播放按钮点击事件
        playButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                playRecording();
            }
        });
    }

    private static final String TAG = "MainActivity";
    static final int bufferSize = AudioRecord.getMinBufferSize(44100,
            AudioFormat.CHANNEL_IN_MONO, AudioFormat.ENCODING_PCM_16BIT) * 2;

    private void startRecording() {
        if (false) {
            mediaRecorder = new MediaRecorder();
            mediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
            mediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);
            mediaRecorder.setOutputFile(fileName);
            mediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);

            try {
                mediaRecorder.prepare();
            } catch (IOException e) {
                e.printStackTrace();
            }

            mediaRecorder.start();
        } else {
            if (ActivityCompat.checkSelfPermission(this, Manifest.permission.RECORD_AUDIO) != PackageManager.PERMISSION_GRANTED) {
                // TODO: Consider calling
                //    ActivityCompat#requestPermissions
                // here to request the missing permissions, and then overriding
                //   public void onRequestPermissionsResult(int requestCode, String[] permissions,
                //                                          int[] grantResults)
                // to handle the case where the user grants the permission. See the documentation
                // for ActivityCompat#requestPermissions for more details.
                return;
            }
            mBufferQueue.clear();

            mAudioRecord = new AudioRecord(MediaRecorder.AudioSource.MIC, 44100, AudioFormat.CHANNEL_IN_MONO, AudioFormat.ENCODING_PCM_16BIT, bufferSize);
            try {
                mAudioRecord.startRecording();
            } catch (IllegalStateException e) {
                Log.w(TAG, "startRecording", e);
            }
            mSaveAudioThread = new Thread(() -> {
                FileOutputStream fos = null;
                try {
                    fos = new FileOutputStream(fileName);
                } catch (FileNotFoundException e) {
                    throw new RuntimeException(e);
                }

                while (!mSaveAudioThread.isInterrupted()) {
                    try {
                        Buffer data = mBufferQueue.take();
                        if (data.bufferSize == 0) {
                            Log.w(TAG, "停止保存Audio");
                            break;
                        }
                        try {
                            fos.write(data.buffer, 0, data.bufferSize);
                        } catch (IOException e) {
                            Log.w(TAG, "write", e);
                        }
                    } catch (InterruptedException e) {
                        Log.w(TAG, "saveAudioThread", e);
                    }
                }
                if (fos != null) {
                    try {
                        fos.close();
                    } catch (IOException e) {

                    }
                }
            });
            mSaveAudioThread.start();
            mReadAudioThread = new Thread(() -> {
                while (!mReadAudioThread.isInterrupted()) {
                    byte[] buffer = new byte[bufferSize];
                    int read = mAudioRecord.read(buffer, 0, bufferSize);
                    if (read > 0) {
                        Buffer data = new Buffer(read);
                        System.arraycopy(buffer, 0, data.buffer, 0, read);
                        mBufferQueue.offer(data);
                    }
                }
                mBufferQueue.clear();
                mBufferQueue.offer(new Buffer(0));
            });
            mReadAudioThread.start();
        }
        Toast.makeText(this, "开始录音", Toast.LENGTH_SHORT).show();
    }

    private void stopRecording() {
        if (true) {
            mReadAudioThread.interrupt();
            if (mAudioRecord != null) {
                try {
                    mAudioRecord.stop();
                    mAudioRecord.release();
                } catch (IllegalStateException e) {
                } finally {
                    mAudioRecord = null;

                }
            }
            return;
        }
        if (mediaRecorder != null) {
            mediaRecorder.stop();
            mediaRecorder.release();
            mediaRecorder = null;
            Toast.makeText(this, "录音结束", Toast.LENGTH_SHORT).show();
        }
    }

    AudioTrack mAudioTrack;
    Thread mPlayThread;

    private void playRecording() {
        if (true) {
            try {

                mAudioTrack = new AudioTrack(AudioManager.STREAM_MUSIC, 44100, AudioFormat.CHANNEL_OUT_MONO, AudioFormat.ENCODING_PCM_16BIT, bufferSize, AudioTrack.MODE_STREAM);
                mAudioTrack.play();
                mPlayThread = new Thread(() -> {
                    FileInputStream fileInputStream = null;
                    try {
                        Log.w(TAG, "开始播放Audio..."+fileName);
                        fileInputStream = new FileInputStream(fileName);
                    } catch (FileNotFoundException e) {
                        Log.w(TAG, "", e);
                        return;
                    }
                    int read = 0;
                    byte[] buffer = new byte[bufferSize];
                    while (true) {
                        try {
                            if (!(!mPlayThread.isInterrupted() && (read = fileInputStream.read(buffer, 0, bufferSize)) != -1))
                                break;
                        } catch (IOException e) {
                            Log.e(TAG, "play", e);
                        }

                        mAudioTrack.write(buffer, 0, read);

                    }
                });
                mPlayThread.start();
            } catch (IllegalArgumentException e) {
                Log.w(TAG, "playRecording", e);
            }
            return;
        }
        mediaPlayer = new MediaPlayer();
        try {
            mediaPlayer.setDataSource(fileName);
            mediaPlayer.prepare();
            mediaPlayer.start();
            Toast.makeText(this, "播放录音", Toast.LENGTH_SHORT).show();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    @Override
    protected void onStop() {
        super.onStop();
        if (mAudioRecord != null) {
            mAudioRecord.release();
            mAudioRecord = null;
        }
        if (mediaRecorder != null) {
            mediaRecorder.release();
            mediaRecorder = null;
        }
        if (mediaPlayer != null) {
            mediaPlayer.release();
            mediaPlayer = null;
        }
    }

    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
        if (requestCode == REQUEST_RECORD_AUDIO_PERMISSION) {
            if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                Toast.makeText(this, "权限已授予", Toast.LENGTH_SHORT).show();
            } else {
                Toast.makeText(this, "权限被拒绝", Toast.LENGTH_SHORT).show();
            }
        }
    }
}